#ifndef INFINITY_SERVICE_GRAPHICS_H
#	define INFINITY_SERVICE_GRAPHICS_H

#include "graphics/backend.h"

#include "service.h"

#include "planet.h"
#include "planeteventlistener.h"
#include "planeteventarg.h"
#include "inputs/command.h"

namespace dw {
	namespace graphics {
		class VertexFormat;
	} // namespace graphics
} // namespace dw

namespace infinity {
	namespace graphics {
		class Model;
		class Mesh;
		class Pipeline;
	} // namespace graphics

class ServiceGraphics
:	public Service
{
public : //! @name Constants
	//! @{
	static const ServiceKey Key;

	static const std::string CollectiblesBlocksPath;
	static const std::string CollectiblesItemsPath;
	//! @}

public : //! @name Types definitions
	//! @{
	typedef Service super;

	enum Pipelines
	{
		PIPELINE_TERRAIN_SOLID = 0,
		PIPELINE_TERRAIN_WIREFRAME,

		PIPELINE_ENTITIES_SOLID,
		PIPELINE_ENTITIES_WIREFRAME,

		PIPELINE_DEBUG_SOLID,
		PIPELINE_DEBUG_WIREFRAME,

		PIPELINE_USER_INTERFACE,

		PIPELINES_COUNT
	};

	enum Groups
	{
		GROUP_TERRAIN = 0,
		GROUP_ENTITIES,
		GROUP_DEBUG,
		GROUP_USER_INTERFACE,

		GROUPS_COUNT
	};

	struct GroupSetup
	{
		dw::graphics::VertexFormat* vertexFormat;
		dw::uint32 pipelinesBits;
	};
	//! @}

public : //! @name Commands
	//! @{
	template< class MeshT >
	graphics::Mesh* createMesh(Groups group, const std::string& name);
	graphics::Model* createModel(Groups group, const std::string& meshName);

	graphics::Model* createModel(Groups group);
	void releaseModel(graphics::Model* model);
	//! @}

protected : //! @name Service callbacks
	//! @{
	virtual State onInitializeMedia();
	virtual void onUpdateMedia(dw::float32 deltaT);
	virtual State onTerminateMedia();
	//! @}

private : //! @name Types definitions
	//! @{
	typedef std::vector< graphics::Pipeline* > PipelinesCollection;
	typedef std::map< std::string, graphics::Mesh* > MeshesCollection;
	//! @}

private : //! @name Construction & Destruction
	//! @{
	ServiceGraphics();
	virtual ~ServiceGraphics();

	friend class ServiceManager;
	//! @}

private : //! @name Internal helpers
	//! @{
	void initializeGroups();
	void initializePipelines();
	void initializeMeshes();
	void initializeCollectiblesBlocksMeshes();
	void initializeCollectiblesItemsMeshes();
	//! @}

private : //! @name Data
	//! @{
	dw::graphics::Backend::RenderWindow* m_renderWindow;
	PipelinesCollection m_pipelines;
	MeshesCollection m_meshes;
	GroupSetup m_groups[GROUPS_COUNT];
	dw::inputs::InputCommand m_toggleWireframe;
	//! @}
};

} // namespace infinity

#include "servicegraphics.inl"

#endif // !INFINITY_SERVICE_GRAPHICS_H
